﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Xml.Linq;

namespace DBAccessTestFramework.Tests
{
    [TestClass]
    public class DatasetElementTest
    {
        [TestMethod]
        public void Load_GivenInputWithInvalidElementName_AnExceptionMustBeRaised()
        {
            string xml = @"<an-invalid-element/>";
            string expectedMessage = "Invalid element name: 'an-invalid-element'. Expected: 'dataset'.";

            try
            {
                this.ExecuteLoad(xml);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }

            Assert.Fail("The expected exception was not raised.");
        }

        [TestMethod]
        public void Load_GivenInput_TestName()
        {
            string xml = @"<dataset name=""ds1"" />";

            var actual = this.ExecuteLoad(xml);
            Assert.AreEqual("ds1", actual.Name);
        }

        [TestMethod]
        public void Load_GivenInput_TestData()
        {
            string xml = @"<dataset name=""ds1"" >
    <data attr1=""v1"" />
</dataset>";

            var actual = this.ExecuteLoad(xml);

            Assert.IsNotNull(actual.Data);
            Assert.AreEqual("<data attr1=\"v1\" />", actual.Data.ToString());
        }

        [TestMethod]
        public void Load_GivenInputWithMissingAttributeName_AnExceptionMustBeRaised()
        {
            string xml = @"<dataset/>";
            string expectedMessage = "Element: 'dataset'. Attribute 'name' is required.";

            try
            {
                this.ExecuteLoad(xml);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }

            Assert.Fail("The expected exception was not raised.");
        }

        [TestMethod]
        public void Load_GivenInputWithInvalidAttribute_AnExceptionMustBeRaised()
        {
            string xml = @"<dataset name=""ds1"" an-invalid-attribute=""s1"" />";
            string expectedMessage = "Element: 'dataset'. Invalid attribute 'an-invalid-attribute'.";

            try
            {
                this.ExecuteLoad(xml);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }

            Assert.Fail("The expected exception was not raised.");
        }

        [TestMethod]
        public void Load_GivenInputWithMoreThanOneChild_AnExceptionMustBeRaised()
        {
            string xml = @"<dataset name=""ds1"" >
    <data attr1=""v1"" />
    <data attr1=""v2"" />
</dataset>";
            string expectedMessage = "Element 'dataset' can have one child only.";

            try
            {
                this.ExecuteLoad(xml);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }

            Assert.Fail("The expected exception was not raised.");
        }

        [TestMethod]
        public void Load_GivenInputWithInvalidChild_AnExceptionMustBeRaised()
        {
            string xml = @"<dataset name=""ds1"" >
    <an-invalid-element attr1=""v1"" />
</dataset>";
            string expectedMessage = "Element: 'dataset'. Invalid child name 'an-invalid-element'. Expected: 'data'.";

            try
            {
                this.ExecuteLoad(xml);
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }

            Assert.Fail("The expected exception was not raised.");
        }

        private DatasetElement ExecuteLoad(string xmlText)
        {
            XElement xml = XElement.Parse(xmlText);
            return DatasetElement.Load(xml);
        }
    }
}
